/**
 * 
 */
package org.jim.server.command;

import org.jim.core.ImChannelContext;
import org.jim.core.ImConst;
import org.jim.core.packets.Message;
import org.jim.server.ImServerChannelContext;
import org.jim.server.adapter.BaseMessageConverter;
import org.jim.server.adapter.MessageConverter;
import org.jim.server.adapter.MessageConverterFactory;
import org.jim.server.processor.ProtocolCmdProcessor;
import org.jim.server.processor.SingleProtocolCmdProcessor;
import org.jim.server.processor.MultiProtocolCmdProcessor;
import org.jim.server.queue.MsgQueueRunnable;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 版本: [1.0]
 * 功能说明: 
 * @author: WChao 创建时间: 2017年9月11日 下午2:07:44
 */
public abstract class AbstractCmdHandler implements CmdHandler, ImConst {
	/**
	 * 单协议业务处理器
	 */
	private SingleProtocolCmdProcessor singleProcessor;
	/**
	 * 多协议业务处理器
	 */
	private List<MultiProtocolCmdProcessor> multiProcessors = new ArrayList<>();

	public AbstractCmdHandler() {};

	public SingleProtocolCmdProcessor getSingleProcessor() {
		return singleProcessor;
	}

	public AbstractCmdHandler setSingleProcessor(SingleProtocolCmdProcessor singleProcessor) {
		this.singleProcessor = singleProcessor;
		return this;
	}

	public <T> T getSingleProcessor(Class<T> clazz) {
		return (T)singleProcessor;
	}

	public AbstractCmdHandler addMultiProtocolProcessor(MultiProtocolCmdProcessor processor) {
		this.multiProcessors.add(processor);
		return this;
	}

	/**
	 * 根据当前通道所属协议获取cmd业务处理器
	 * @param imChannelContext
	 * @return
	 */
	public <T> T getMultiProcessor(ImChannelContext imChannelContext, Class<T> clazz){
		T multiCmdProcessor = null;
		for(MultiProtocolCmdProcessor multiProcessor : multiProcessors){
			if(multiProcessor.isProtocol(imChannelContext)){
				multiCmdProcessor = (T)multiProcessor;
			}
		}
		return multiCmdProcessor;
	}
	/**
	 * 获取聊天业务处理异步消息队列
	 * @param imServerChannelContext IM通道上下文
	 * @return
	 */
	private MsgQueueRunnable getMsgQueueRunnable(ProtocolCmdProcessor protocolCmdProcessor,ImServerChannelContext imServerChannelContext){
		MsgQueueRunnable msgQueueRunnable = (MsgQueueRunnable)imServerChannelContext.getMsgQue();
		if(Objects.nonNull(msgQueueRunnable.getProtocolCmdProcessor())){
			return msgQueueRunnable;
		}
		synchronized (MsgQueueRunnable.class){
			msgQueueRunnable.setProtocolCmdProcessor(protocolCmdProcessor);
		}
		return msgQueueRunnable;
	}
	/**
	 * 添加消息到队列进行异步处理
	 * @param channelContext
	 * @param msg
	 */
	public void addQueueMsgProcessor(ProtocolCmdProcessor protocolCmdProcessor,ImChannelContext channelContext, Message msg){
		ImServerChannelContext imServerChannelContext = (ImServerChannelContext)channelContext;
		MsgQueueRunnable msgQueueRunnable = getMsgQueueRunnable(protocolCmdProcessor,imServerChannelContext);
		msgQueueRunnable.addMsg(msg);
		msgQueueRunnable.executor.execute(msgQueueRunnable);
	}
	/**
	 * 设置消息转换器
	 * @param messageConverter
	 */
	public void setMessageConverter(MessageConverter messageConverter){
		messageConverter.setCmd(command());
		MessageConverterFactory.addConverter(messageConverter);
	}
}
